package day13;

import java.util.*;

/**
 *给你一个整数数组 nums ，和一个表示限制的整数 limit，请你返回最长连续子数组的长度，该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。
 *
 * 如果不存在满足条件的子数组，则返回 0 。
 *
 *
 *
 * 示例 1：
 *
 * 输入：nums = [8,2,4,7], limit = 4
 * 输出：2
 * 解释：所有子数组如下：
 * [8] 最大绝对差 |8-8| = 0 <= 4.
 * [8,2] 最大绝对差 |8-2| = 6 > 4.
 * [8,2,4] 最大绝对差 |8-2| = 6 > 4.
 * [8,2,4,7] 最大绝对差 |8-2| = 6 > 4.
 * [2] 最大绝对差 |2-2| = 0 <= 4.
 * [2,4] 最大绝对差 |2-4| = 2 <= 4.
 * [2,4,7] 最大绝对差 |2-7| = 5 > 4.
 * [4] 最大绝对差 |4-4| = 0 <= 4.
 * [4,7] 最大绝对差 |4-7| = 3 <= 4.
 * [7] 最大绝对差 |7-7| = 0 <= 4.
 * 因此，满足题意的最长子数组的长度为 2 。
 * 示例 2：
 *
 * 输入：nums = [10,1,2,4,7,2], limit = 5
 * 输出：4
 * 解释：满足题意的最长子数组是 [2,4,7,2]，其最大绝对差 |2-7| = 5 <= 5 。
 * 示例 3：
 *
 * 输入：nums = [4,2,2,2,4,4,2,2], limit = 0
 * 输出：3
 *
 *
 */
public class Solution3 {
    public int longestSubarray(int[] nums, int limit) {
        Deque<Integer> queueMax = new LinkedList<>();
        Deque<Integer> queueMin = new LinkedList<>();
        int ans = 0, l = -1, r = 0;
        while (r < nums.length) {
            int num = nums[r];
            while (!queueMax.isEmpty() && nums[queueMax.peekLast()] <= num) {// 维护最大值单调队列
                queueMax.pollLast();
            }
            queueMax.add(r);
            while (!queueMin.isEmpty() && nums[queueMin.peekLast()] >= num) {// 维护最小值单调队列
                queueMin.pollLast();
            }
            queueMin.add(r);
            while (l < r && Math.abs(nums[queueMax.peekFirst()] - num) > limit) {// 通过limit调整左端l
                l = queueMax.pollFirst();
            }
            while (l < r && queueMin.peekFirst() < l) {// 因为大队调整造成小队左端失效
                queueMin.pollFirst();
            }
            while (l < r && Math.abs(nums[queueMin.peekFirst()] - num) > limit) {// 通过limit调整左端l
                l = queueMin.pollFirst();
            }
            ans = Math.max(ans, r - l);// 有效窗口[l+1,r]
            r++;
        }
        return ans;
    }
}
